#!/usr/bin/env python
# encoding: utf-8

from datetime import datetime
from util import Xml

class Kml:
    """ Kml文件解释器，只针对两步路的单条轨迹的导出格式。未测试其它Kml文件。 """

    def __init__(self, kml_file):
        xml_content = open(kml_file).read().replace("xmlns", "xx").replace("gx:", "").replace(":gx", "1")

        root = Xml.parse_text(xml_content)
        document = root.get_child("Document")
        self.document = document

        self.name = document.get_child("name").get_text()
        self.description = document.get_child("description").get_text()
        self.author = document.get_child("author").get_text()

        for folder in document.get_children("Folder"):
            if folder.get_attr("id") == "TbuluTrackFolder":
                break

        placemark = folder.get_child("Placemark")
        desc = placemark.get_child("description")

        self.max_height = Kml.description_data(desc, "最高海拔")
        self.min_height = Kml.description_data(desc, "最低海拔")
        self.distance = Kml.description_data(desc, "累计里程")
        self.cum_up = Kml.description_data(desc, "累计爬升")
        self.cum_down = Kml.description_data(desc, "累计下降")

        self.points = Kml.get_points(placemark)

    @staticmethod
    def description_data(desc, prefix):
        for div in desc.get_children("div"):
            text = div.get_text()
            if text.startswith(prefix):
                return float(text[len(prefix) + 1 : -1])

        return None

    @staticmethod
    def get_points(placemark):
        track = placemark.get_child("Track")

        cords = [[float(x) for x in cord.get_text().split()] for cord in track.get_children("coord")]
        whens = [datetime.fromisoformat(x.get_text().replace("Z", "+00:00")).astimezone().strftime("%Y-%m-%d %H:%M:%S")
                for x in track.get_children("when")]

        return [[when, *cord] for when, cord in zip(whens, cords)]

    def extend_data(self, data_name):
        for child in self.document.get_child("ExtendData").get_children("Data"):
            if child.get_attr("name") == data_name:
                return child.get_child("value").get_text()

        return None

    def distance(self):
        return


    def calc_cum_up_down(self, ignore):
        points = self.points[:]
        while True:
            merged = merge(points)
            removed = remove_minimum(merged, ignore)

            if len(removed) == len(points):
                alts = [p1[3] - p0[3] for p0, p1 in zip(removed[:-1], removed[1:])]
                times = [p[0] for p in removed]

                return (sum([alt for alt in alts if alt > 0]),
                        sum([alt for alt in alts if alt < 0]),
                        removed,
                        [ p if p[0] in times else [*p[:3], ""] for p in self.points ])
            else:
                points = removed


def merge(points):
    """ 合并爬升、下降路段 """

    current_direction = points[1][3] - points[0][3]
    merged = [points[0], ]

    for (p1, p2) in zip(points[:-1], points[1:]):
        alt = p2[3] - p1[3]
        if alt * current_direction >= 0:
            current_direction = p2[3] - merged[-1][3]
        else:
            merged.append(p1)
            current_direction = alt

    merged.append(points[-1])

    return merged

def remove_minimum(points, ignore):
    """ 删除海拔变化最短的一段的路径 """

    if len(points) <= 2:    return points

    alts = [abs(p2[3] - p1[3]) for p1, p2 in zip(points[:-1], points[1:])]
    min_alt = min(alts)
    if min_alt > ignore:
        return points

    min_i = alts.index(min_alt)

    if min_i == 0:
        return [points[0], *points[2:]]
    elif min_i == len(alts) - 1:
        return [*points[:-2], points[1]]
    else:
        return [*points[:min_i], *points[min_i+2:]]
